package unimelb.filesync.client.protocol;

import java.security.PublicKey;

import unimelb.filesync.common.crypto.CryptoUtils;
import unimelb.filesync.common.message.NetworkMessage;
import unimelb.filesync.common.message.RequestPublicKey;
import unimelb.filesync.common.message.ResponsePublicKey;
import unimelb.filesync.common.misc.ProtocolContext;
import unimelb.filesync.common.network.NetworkConnection;
import unimelb.filesync.common.network.NetworkService;
import unimelb.filesync.common.protocol.IFileSyncPhase;

public class GetPublicKeyPhase implements IFileSyncPhase {
    private final ProtocolContext context;

    private final CryptoUtils cryptoUtils;

    private final NetworkService networkService;

    public GetPublicKeyPhase(ProtocolContext context) {
        super();
        this.context = context;
        this.cryptoUtils = new CryptoUtils();
        this.networkService = new NetworkService();
    }

    @Override
    public void execute() {
        final NetworkConnection connection = context.getObject(ProtocolContext.HOT_LINE_CONNECTION);
        final String serverIp = connection.getDestinationIp();

        PublicKey publicKey = null;
        if (cryptoUtils.isRsaPublicKeyFileExist(serverIp)) {
            System.out.println("Public key is cached locally. Reading from file");
            publicKey = cryptoUtils.readRsaPublicKey(serverIp);

            networkService.writeMessage(NetworkMessage.createPublicKeyRequestMsg(new RequestPublicKey(false)), connection);
            networkService.readMessage(connection);
        } else {
            System.out.println("Public key does not exist. Requesting public key from server");
            networkService.writeMessage(NetworkMessage.createPublicKeyRequestMsg(new RequestPublicKey(true)), connection);
            final NetworkMessage response = networkService.readMessage(connection);
            if (response == null) {
                System.exit(0);
            }

            final ResponsePublicKey content = response.getContent();
            publicKey = cryptoUtils.decodePublicKey(content.getPublicKey());
            cryptoUtils.saveRsaPublicKey(serverIp, publicKey);
        }

        context.addObject(ProtocolContext.PUBLIC_KEY, publicKey);
    }

}
